package org.jeecg.chase.common.script.dao;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.chase.common.base.data.BaseQuery;
import org.jeecg.chase.common.dataaccess.core.BaseNamedParameterJdbcTemplate;
import org.jeecg.chase.common.dataaccess.data.PageRequest;
import org.jeecg.chase.common.dataaccess.data.PageResultSetExtractor;
import org.jeecg.chase.common.script.controller.CommonDataController;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.support.ThreadLocalHolder;
import org.jeecg.common.util.IPUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author leikai
 * @version 1.0
 * @description: 通用Dao
 * @date 2021/07/23/0023 18:23
 */
@Repository
public class CommonDataDao {
    @Autowired
    private BaseNamedParameterJdbcTemplate baseNamedParameterJdbcTemplate;

    public List<?> getList(BaseQuery baseQuery, Class elementType) {
        long beginTime = System.currentTimeMillis();
        String sql = baseQuery.getSql();
        List list = null;
        if (null == elementType) {
            list = baseNamedParameterJdbcTemplate.queryForListHump(sql, baseQuery);
        } else {
            list = baseNamedParameterJdbcTemplate.queryForList(sql, baseQuery, elementType);
        }
        long time = System.currentTimeMillis() - beginTime;
        this.saveLog(baseQuery, CommonDataController.class.getName() + ".getList()", "列表查询", time);
        return list;
    }


    public Page<?> getPage(BaseQuery baseQuery, Class elementType) {
        long beginTime = System.currentTimeMillis();
        String sql = baseQuery.getSql();
        PageRequest pageRequest = baseQuery.getPageRequest();
        Page page = new Page(pageRequest.getPageNo(), pageRequest.getPageSize());
        PageResultSetExtractor<?> pageResult;
        if (null == elementType) {
            pageResult = baseNamedParameterJdbcTemplate.queryForPageHump(pageRequest, sql, baseQuery);
        } else {
            pageResult = this.baseNamedParameterJdbcTemplate.queryForPage(pageRequest, sql, baseQuery, elementType);
        }
        page.setTotal(pageResult.getTotal());
        page.setRecords(pageResult.getResult());
        long time = System.currentTimeMillis() - beginTime;
        this.saveLog(baseQuery, CommonDataController.class.getName() + ".getPage()", "分页查询", time);
        return page;
    }

    public long getForLong(final String sql, Object object) {
        String countSql = prepareCountSql(sql);
        try {
            return baseNamedParameterJdbcTemplate.queryForLong(countSql, object);
        } catch (Exception e) {
            throw new RuntimeException("orm-jdbc-003:无法计算记录总数, sql is:" + countSql, e);
        }
    }

    public long queryForLong(String sql, Object object) {
        return baseNamedParameterJdbcTemplate.queryForLong(sql, object);
    }

    private String prepareCountSql(String sql) {
        String countSql = " select count(*) from ( ".concat(removeOrderBy(sql)).concat(" ) countRows");
        return countSql;
    }

    private String removeOrderBy(String sql) {
        int beginPos = sql.toLowerCase().indexOf(" order ");
        if (beginPos == -1) {
            return sql;
        }
        String orderStr = sql.substring(beginPos);
        int rightParenthesisIndex = orderStr.indexOf(")");
        if (rightParenthesisIndex == -1) {
            return sql.substring(0, beginPos);
        }
        return sql;
    }

    public Object get(BaseQuery baseQuery, Class elementType) {
        long beginTime = System.currentTimeMillis();
        String sql = baseQuery.getSql();
        List list = null;
        if (null == elementType) {
            list = baseNamedParameterJdbcTemplate.queryForListHump(sql, baseQuery);
        } else {
            list = baseNamedParameterJdbcTemplate.queryForList(sql, baseQuery, elementType);
        }
        long time = System.currentTimeMillis() - beginTime;
        this.saveLog(baseQuery, CommonDataController.class.getName() + ".getList()", "详情查询", time);
        if (list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    public int getForInt(String sql, Object paramObject) {
        return this.baseNamedParameterJdbcTemplate.queryForInt(sql, paramObject);
    }

    public List<Map<String, Object>> queryForListHump(String sql, Object paramObject) {
        return this.baseNamedParameterJdbcTemplate.queryForListHump(sql, paramObject);
    }

    public List<?> queryForList(String sql, Object paramObject, Class elementType) {
        return this.baseNamedParameterJdbcTemplate.queryForList(sql, paramObject, elementType);
    }

    public void batchExecute(String[] sqls, Map<String, Object> paramMap) {
        baseNamedParameterJdbcTemplate.batchExecute(sqls, paramMap);
    }

    public Map<String, Object> queryForMapHump(String sql, Object paramObject) {
        return baseNamedParameterJdbcTemplate.queryForMapHump(sql, paramObject);
    }

    public Map<String, Object> queryForMap(String sql, Object paramObject) {
        return baseNamedParameterJdbcTemplate.queryForMap(sql, paramObject);
    }

    public void execute(String sql) {
        baseNamedParameterJdbcTemplate.execute(sql);
    }

    private void saveLog(BaseQuery baseQuery, String methodStr, String suffixStr, long time) {
        try {
            Method method = baseQuery.getClass().getMethod("getQuerySql", null);
            AutoLog annotation = method.getAnnotation(AutoLog.class);
            if (annotation != null) {
                String ipAddress;
                try {
                    HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
                    ipAddress = IPUtils.getIpAddr(request);
                } catch (Exception e) {
                    ipAddress = "127.0.0.1";
                }
                String sql = "insert into sys_log (id, log_type, log_content, method, operate_type, request_param, userid, username, create_time, ip, cost_time) values (:id, :logType, :logContent, :method, :operateType, :requestParam, :userId, :userName, :createTime, :ipAddress, :costTime)";
                String requestParam = baseQuery.getValueMap().toString();
                String userId = ThreadLocalHolder.getLoginUser().getUsername();
                String userName = ThreadLocalHolder.getLoginUser().getRealname();
                Map<String, Object> param = new HashMap<>();
                param.put("id", UUID.randomUUID().toString().replaceAll("-", ""));
                param.put("logType", annotation.logType());
                param.put("logContent", annotation.value() + "-" + suffixStr);
                param.put("method", methodStr);
                param.put("operateType", annotation.operateType());
                param.put("requestParam", requestParam);
                param.put("userId", userId);
                param.put("userName", userName);
                param.put("createTime", new Date());
                param.put("ipAddress", ipAddress);
                param.put("costTime", time);
                this.baseNamedParameterJdbcTemplate.batchExecute(new String[]{sql}, param);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
